#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project ：pyspark 
@File    ：JaccardSimilarity.py
@IDE     ：PyCharm 
@Author  ：Amos.Mu
@Date    ：2022/5/14 16:50 
'''
import json

'''
基于用户的相似度：基于用户消费记录找到相似的用户
基于物品的相似度：基于用户的消费记录找到相似的物品
'''
import numpy as np
import pandas as pd

'''
1. 创建数据集
'''
users = ["user1", "user2", "user3", "user4", "user5"]
items = ["Item A", "Item B", "Item C", "Item D", "Item E"]

# 用户购买记录数据集  5x5的矩阵
datasets = [
    [1, 0, 1, 1, 0],
    [1, 0, 0, 1, 1],
    [1, 0, 1, 0, 0],
    [0, 1, 0, 1, 1],
    [1, 1, 1, 0, 1]
]
# 将datasets转成 dataframe。每一列是一个物品，每一行是一个user
df = pd.DataFrame(datasets, columns=items, index=users)
print(df)

from sklearn.metrics import jaccard_score
from sklearn.metrics.pairwise import pairwise_distances

# 1/5 Item A和Item B ==> 交集是1 并集是5
score = jaccard_score(df['Item B'], df['Item A'])
print(score)

'''
2.基于杰卡德求用户的相似度
'''
user_similar = 1 - pairwise_distances(df.values, metric='jaccard')
user_similar = pd.DataFrame(user_similar, columns=users, index=users)
print(user_similar)
'''
3.基于杰卡德求物品的相似度
'''
item_similar = 1 - pairwise_distances(df.T.values, metric='jaccard')
item_similar = pd.DataFrame(item_similar, columns=items, index=items)
print(item_similar)

'''
4.为每一个用户创建一个字典，为每一个用户找到相似的两个用户
'''

topN_users = {}
for i in user_similar:
    # 取出每一列数据，删除自己，按照相似度排序
    _df = user_similar.loc[i].drop([i])
    _df_sorted = _df.sort_values(ascending=False)
    top2 = list(_df.index[:2])
    topN_users[i] = top2
# 打印字典Json时换行输出
print(json.dumps(topN_users, indent=1))

'''
5.根据topn的相似用户构建推荐结果
'''
results = {}
users_values = topN_users.values()
for user, sim_users in topN_users.items():
    result = set()  # 为每一用户保存推荐结果
    for sim_user in sim_users:
        result = result.union(set(df.loc[sim_user].replace(0, np.nan).dropna().index))
    # 过滤掉已经购买的商品
    result -= set(df.loc[user].replace(0, np.nan).dropna().index)
    results[user] = result

print(results)
